# -*- coding: utf-8 -*-
#****************************************************************************
#                                程序主界面
#   1.提供用户输入目标地址
#   2.判断是否有解析器能够处理
#****************************************************************************
import os
import sys
import time
import threading
import importlib

from PyQt5.QtWidgets import ( QApplication,QMainWindow,QWidget,QVBoxLayout,QHBoxLayout,QLabel,QScrollArea,QGridLayout,QPushButton,QProgressBar )
from PyQt5.QtGui import QIcon,QPixmap

# 加载主界面UI
from comicui import *
# 对应tab的工作线程
from ergate import *
#from Ergate import *
# 用户自定义UI界面 tab,checkbox
from customui import CCTabWidget as TabWidget

# ----------------------------------------  数据结构  ----------------------------------------

# 任务单元：对应每个链接会产生一个tab的界面+相对应的工作线程
class CUnit(object):
    def __init__(self,url='',ergate=None,ui=None):
        self.url=url                    # 漫画地址
        self.ergate=ergate              # 工作线程
        self.ui=ui                      # tab界面

# 解析器
class CParser(object):
    def __init__(self,resolver=None,tag=''):
        self.resolver=resolver          # 解析器
        self.tag=tag                    # 解析器标签

# ----------------------------------------  工作线程  ----------------------------------------

raw_url_mutex=threading.Lock()
ready_url_mutex=threading.Lock()
class Hamburg(threading.Thread):
    def __init__(self,armor):
        threading.Thread.__init__(self)
        self.armor=armor
    def run(self):
        while True:
            if len(self.armor.raw_urls)>0:
                raw_url_mutex.acquire()
                url=self.armor.raw_urls[0]
                self.armor.raw_urls.remove(url)
                raw_url_mutex.release()
                # 测试是否在工作单元中
                print('test url:',url)
                is_in_units=False
                for unit in self.armor.units:
                    if url==unit.url:
                        is_in_units=True
                        #print('already exist')
                        continue
                if is_in_units: continue
                ready_url_mutex.acquire()
                self.armor.ready_urls.append(url)
                ready_url_mutex.release()
                self.armor.ui.btn_url.clicked.emit()
                

# ----------------------------------------  程序实体  ----------------------------------------

# 程序实体需要管理：界面；窗口；解析器列表；任务单元列表
class Armor():
    def __init__(self,ui=None,window=None):
        self.ui=ui                      # 程序的用户区部分
        self.win=window                 # 程序的窗口
        self.units=[]                   # 任务单元列表
        self.parsers=[]                 # 解析器列表
        self.raw_urls=[]
        self.ready_urls=[]
        self.ham=None

        self.patchs()                    # 补丁

    # 补丁：窗口管理；事件触发；任务单元列表初始化；解析器列表构建
    def patchs(self):
        self.patch_path()
        self.patch_wins()
        self.patch_ui_events()
        self.patch_units()
        self.patch_parsers()        
        self.path_threads()
    
    # 用于包，模块的寻找
    def patch_path(self):
        sys.path.append('./cparser')

    # 窗口管理：添加icon等……
    def patch_wins(self):
        pass

    # 1.搜索按钮事件；
    # 2.关闭tab页面事件；
    # 3.添加tab页面事件
    def patch_ui_events(self):
        self.ui.btn_search.clicked.connect(self.button_search_pressed)
        self.ui.body.tabCloseRequested.connect(self.close_tab)
        self.ui.body.tabBarClicked.connect(self.tabbar_add)
        self.ui.btn_url.clicked.connect(self.add_unit)
    
    # 解析器初始化
    # 第一个tab页面不提供任何任务，也无法删除
    def patch_units(self):
        self.units.append(CUnit())

    # 解析器列表初始化 
    # 查找程序目录parsers下的所有解析器
    def patch_parsers(self):
        ComicCave_dir=os.getcwd()
        sys.path.append(ComicCave_dir)
        parsers_dir=ComicCave_dir+'\\'+'cparser'
        try:
            pers=os.listdir(parsers_dir)
        except Exception as e:
            print(e)
            print("parsers dir is not exist")
            return
        else:
            for per in pers:
                if '__' in per: continue
                per=per[:-3]
                mod=importlib.import_module('cparser.'+per)
                if mod and hasattr(mod,'url_judgement'):
                    self.parsers.append(CParser(mod,per))
                else:
                    print('non a parser pass')
                    pass
    def path_threads(self):
        self.ham=Hamburg(self)
        self.ham.setDaemon(True)
        self.ham.start()

    # 搜索按钮触发事件 
    # 将要解析的链接放到任务链接表中
    def button_search_pressed(self):
        url=self.ui.le_comic_url.text()
        if not (url in self.raw_urls):
            raw_url_mutex.acquire()
            self.raw_urls.append(url)
            raw_url_mutex.release()
        print('button search pressed over')

    # 关闭指定标签页 
    # 标签0不关闭 
    # 关闭指定标签并从任务单元列表中删除该任务
    def close_tab(self,index=-1):
        if index==-1 or index==0:
            return
        self.ui.body.removeTab(index)
        unit=self.units[index]
        unit.ergate.workover=True               # 停止任务单元的工作线程
        self.units.remove(unit)                 # 删除该任务单元

    # 将完成的初步解析的任务单元的tab界面显示出来
    def tabbar_add(self,index=-1):
        if index==-1 or index==0: return        # 0/1 编号是不可能的
        unit=self.units[index]
        tab=unit.ui
        title=unit.ergate.loader.comic.title
        self.ui.body.addTab(tab,title)
        self.ui.body.setCurrentWidget(tab)      # 跳转到新添加的界面上

    def add_unit(self):
        ready_url_mutex.acquire()
        if len(self.ready_urls)>0:
            url=self.ready_urls[0]
            self.ready_urls.remove(url)
            #print(url)
            loader=self.url_judgement(url)
            if not loader:
                return
            tabui=TabWidget(self.ui.body)
            ergate=Ergate(tabui,loader,self)
            ergate.setDaemon(True)
            ergate.comic_url=url
            ergate.unit_idx=len(self.units)
            ergate.start()
            self.units.append(CUnit(url,ergate,tabui))
        ready_url_mutex.release()

    # 判断是否可以解析该链接 
    # 尝试所有的解析器 
    # 返回解析程序的下载器
    # 无法解析给与提示并返回False
    def url_judgement(self,url):
        for parser in self.parsers:
            loader=parser.resolver.url_judgement(url)
            if loader:
                print(parser.tag,'can parser the url',url)
                return loader        
        QMessageBox.information(self.ui.body,"提示","没有相应的解析器，请下载对应解析器或者提交\n网址到: author@ComicCave.com")
        return False

# ----------------------------------------  程序开始  ----------------------------------------

# 创建窗口 
# 创建窗口UI组件 
# 创建程序实体
#if __name__=='__main__':
app=QApplication(sys.argv)
win=QMainWindow()
ui=Ui_ComicCaveUI()
ui.setupUi(win)
arm=Armor(ui,win)
win.show()
sys.exit(app.exec_())